//***************************************************************************
//   Copyright(c)2020, Xidian University D405.
//   All rights reserved
//
//   IP Name         :   Null
//   File name       :   np_dma_rx_data.v
//   Module name     :   np_dma_rx_data
//   Author          :   Wang Zekun
//   Date            :   2022/05/17
//   Version         :   v1.2
//   Verison History :   v1.0/v1.1/1.2
//   Edited by       :   Wang Zekun
//   Modification history : v1.0 Initial revision
//                          v1.1 add signals from cpt, add mux for rxfifo & cpt by zyc
//                          v1.2 add ports :rxfifo_data_empty0_i, rxfifo_data_emptyi_i, change mux of *leng*.
//                               line 90: rxfifo_data_valid = rxfifo_rd_data_en_ff2.
//
// ----------------------------------------------------------------------------
// Version 1.10      Date(2022/05/05)
// Abstract : rx length and data fifo polling control
//-----------------------------------------------------------------------------
// Programmer's model
//
//-----------------------------------------------------------------------------
//interface list :
//                
module np_dma_rx_data #(
        parameter DMA_DWIDTH = 128 , // DMA Data Width
        parameter LEN_DWIDTH = 20    // LEN Data Width
  )(
  input  wire                           clk_i           ,
  input  wire                           resetn_i        ,

  input  wire                           almost_done_i   ,
  input  wire                           already_done_i  ,
  
  output wire                           rxfifo_rd_data0_en_o,
  input  wire [DMA_DWIDTH-1 : 0]        rxfifo_rd_dout0_i,
  input  wire                           rxfifo_empty0_i,
  input  wire                           rxfifo_data_empty0_i,
  output wire                           rxfifo_rd_leng0_en_o,
  input  wire [LEN_DWIDTH-1 : 0]        rxfifo_rd_leng0_i,

  output wire                           rxfifo_rd_data1_en_o,
  input  wire [DMA_DWIDTH-1 : 0]        rxfifo_rd_dout1_i,
  input  wire                           rxfifo_empty1_i,
  input  wire                           rxfifo_data_empty1_i,
  output wire                           rxfifo_rd_leng1_en_o,
  input  wire [LEN_DWIDTH-1 : 0]        rxfifo_rd_leng1_i,
  
  output wire                           cpt_rd_leng_en_0_o  ,
  output wire                           cpt_rd_data_en_0_o  ,
  input  wire                           cpt_rd_leng_vld_0_i ,
  input  wire                           cpt_rd_dout_vld_0_i ,
  input  wire [ 10:0]                   cpt_rd_leng_0_i     ,
  input  wire [127:0]                   cpt_rd_dout_0_i     ,
  input  wire                           cpt_empty_0_i       ,
	input  wire                           cpt_data_empty_0_i  ,

  output wire                           cpt_rd_leng_en_1_o  ,
  output wire                           cpt_rd_data_en_1_o  ,
  input  wire                           cpt_rd_leng_vld_1_i ,
  input  wire                           cpt_rd_dout_vld_1_i ,
  input  wire [ 10:0]                   cpt_rd_leng_1_i     ,
  input  wire [127:0]                   cpt_rd_dout_1_i     ,
  input  wire                           cpt_empty_1_i       ,
  input  wire                           cpt_data_empty_1_i  ,

  input  wire                           rxfifo_rd_data_en_i,
  output wire [DMA_DWIDTH-1 : 0]        rxfifo_rd_dout_o,
  output wire                           rxfifo_rd_dout_vld_o,
  output wire                           rxfifo_empty_o,
  input  wire                           rxfifo_rd_leng_en_i,
  output wire [LEN_DWIDTH-1 : 0]        rxfifo_rd_leng_o,
  
  input  wire [1 : 0]                   rxfifo_cpt_sel_i,
  output wire                           port_sel_o,
  input  wire                           data_sel_lock_i

);

  wire                          port_sel;
  wire                          port_sel_for_leng_fifo;
  wire [DMA_DWIDTH + LEN_DWIDTH -1 : 0]         rxfifo0_payload;
  wire [DMA_DWIDTH + LEN_DWIDTH -1 : 0]         rxfifo1_payload;
  wire [DMA_DWIDTH + LEN_DWIDTH -1 : 0]         rxfifo_payload;

  assign rxfifo0_payload = {rxfifo_rd_dout0_i,rxfifo_rd_leng0_i,rxfifo_empty0_i};
  assign rxfifo1_payload = {rxfifo_rd_dout1_i,rxfifo_rd_leng1_i,rxfifo_empty1_i};
  
  assign rxfifo_payload  = port_sel ? rxfifo1_payload : rxfifo0_payload;
  
  //assign {rxfifo_rd_dout_o,rxfifo_rd_leng_o,rxfifo_empty_o} = rxfifo_payload;
  
  //****** 2022.05.12 zyc begin******/

  reg    rxfifo_rd_data_en_ff1;
  reg    rxfifo_rd_data_en_ff2;
  wire   rxfifo_data_valid;
  assign rxfifo_data_valid = rxfifo_rd_data_en_ff2;
  reg    rxfifo_rd_leng_en_ff;

  always @(posedge clk_i or negedge resetn_i) 
  begin
    if(~resetn_i)
    begin
      rxfifo_rd_data_en_ff1 <= 1'b0;
      rxfifo_rd_data_en_ff2 <= 1'b0;
      rxfifo_rd_leng_en_ff  <= 1'b0;
    end
    else
    begin
      rxfifo_rd_data_en_ff1 <= rxfifo_rd_data_en_i;
      rxfifo_rd_data_en_ff2 <= rxfifo_rd_data_en_ff1;
      rxfifo_rd_leng_en_ff  <= rxfifo_rd_leng_en_i;
    end
  end

  assign rxfifo_rd_leng_o = (rxfifo_cpt_sel_i == 2'b11) ? (port_sel_for_leng_fifo ? cpt_rd_leng_1_i : cpt_rd_leng_0_i) : (port_sel_for_leng_fifo ? rxfifo_rd_leng1_i : rxfifo_rd_leng0_i);
  assign rxfifo_rd_dout_o = (rxfifo_cpt_sel_i == 2'b11) ? (port_sel ? cpt_rd_dout_1_i : cpt_rd_dout_0_i) : (port_sel ? rxfifo_rd_dout1_i : rxfifo_rd_dout0_i);
  assign rxfifo_empty_o =   (rxfifo_cpt_sel_i == 2'b11) ? (port_sel ? cpt_empty_1_i : cpt_empty_0_i) : (port_sel ? rxfifo_empty1_i : rxfifo_empty0_i);
  
  assign rxfifo_rd_data0_en_o = ((port_sel == 1'b0) && (rxfifo_cpt_sel_i != 2'b11)) ? rxfifo_rd_data_en_i : 1'b0;
  assign rxfifo_rd_data1_en_o = ((port_sel == 1'b1) && (rxfifo_cpt_sel_i != 2'b11)) ? rxfifo_rd_data_en_i : 1'b0;
  assign cpt_rd_data_en_0_o   = ((port_sel == 1'b0) && (rxfifo_cpt_sel_i == 2'b11)) ? rxfifo_rd_data_en_i : 1'b0;
  assign cpt_rd_data_en_1_o   = ((port_sel == 1'b1) && (rxfifo_cpt_sel_i == 2'b11)) ? rxfifo_rd_data_en_i : 1'b0;
  
  assign rxfifo_rd_leng0_en_o = ((port_sel_for_leng_fifo == 1'b0) && (rxfifo_cpt_sel_i != 2'b11)) ? rxfifo_rd_leng_en_ff : 1'b0;
  assign rxfifo_rd_leng1_en_o = ((port_sel_for_leng_fifo == 1'b1) && (rxfifo_cpt_sel_i != 2'b11)) ? rxfifo_rd_leng_en_ff : 1'b0;
  assign cpt_rd_leng_en_0_o   = ((port_sel_for_leng_fifo == 1'b0) && (rxfifo_cpt_sel_i == 2'b11)) ? rxfifo_rd_leng_en_ff : 1'b0;
  assign cpt_rd_leng_en_1_o   = ((port_sel_for_leng_fifo == 1'b1) && (rxfifo_cpt_sel_i == 2'b11)) ? rxfifo_rd_leng_en_ff : 1'b0;
  
  assign rxfifo_rd_dout_vld_o = (rxfifo_cpt_sel_i == 2'b11) ? (port_sel ? cpt_rd_dout_vld_1_i : cpt_rd_dout_vld_0_i) : rxfifo_data_valid;
  
  np_dma_rx_polling u_np_dma_rx_polling(
    .clk_i                      (clk_i),
    .resetn_i                   (resetn_i),
    .rxfifo_empty0_i            ((rxfifo_cpt_sel_i == 2'b11) ? cpt_empty_0_i : rxfifo_empty0_i),
    .rxfifo_data_empty0_i       ((rxfifo_cpt_sel_i == 2'b11) ? cpt_data_empty_0_i : rxfifo_data_empty0_i),
    .rxfifo_empty1_i            ((rxfifo_cpt_sel_i == 2'b11) ? cpt_empty_1_i : rxfifo_empty1_i),
    .rxfifo_data_empty1_i       ((rxfifo_cpt_sel_i == 2'b11) ? cpt_data_empty_1_i : rxfifo_data_empty1_i),
    .almost_done_i              (almost_done_i),
    .already_done_i             (already_done_i),
    .rxfifo_rd_leng_en_i        (rxfifo_rd_leng_en_i),
    .port_sel_o                 (port_sel),
    .port_sel_for_leng_fifo_o   (port_sel_for_leng_fifo),
    .data_sel_lock_i            (data_sel_lock_i)
  );
  
  //****** 2022.05.12 zyc end******/
  
  assign port_sel_o = port_sel_for_leng_fifo;//port_sel;

endmodule